﻿using ED.Common.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using System.Collections.Concurrent;
using System.Net;
using System.Security.Claims;

namespace UserCenter
{
    public class User : IUser
        {
        private readonly IHttpContextAccessor accessor;
        private readonly bool isCoverId;

        /// <summary>
        /// 登录用户构造函数
        /// </summary>
        /// <param name="_accessor"></param>
        /// <param name="isCoverId"></param>
        public User(IHttpContextAccessor _accessor, bool isCoverId = false)
            {
            accessor = _accessor;
            this.isCoverId = isCoverId;
            }
        public virtual int? CoverId { get; set; }
        /// <summary>
        /// 用户Id
        /// </summary>
        public virtual int Id
            {
            get
                {
                if (isCoverId && CoverId.HasValue)
                    {
                    return CoverId.Value;
                    }

                int tmp = 1;
                StringValues un = new();
                bool? existInHeader = accessor?.HttpContext?.Request?.Headers?.TryGetValue("un", out un);
                if (existInHeader == true)
                    {
                    string undecode = WebUtility.UrlDecode(un[0]);
                    string[] unarr = undecode.SplitAndTrim(':');
                    if (unarr.IsNotNullOrEmpty() && unarr.Length >= 1 && unarr[0].IsNotNullOrEmptyOrWhiteSpace())
                        {
                        return unarr[0].To<int>();
                        }
                    }

                Claim claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "id").FirstOrDefault();
                if (claim != null && !string.IsNullOrEmpty(claim.Value))
                    {
                    tmp = Convert.ToInt32(claim.Value);
                    }

                if (accessor?.HttpContext?.User?.Identity.AuthenticationType == "AuthenticationTypes.Federation")
                    {
                    //集成identityserver
                    claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "sub").FirstOrDefault();
                    if (claim != null && !string.IsNullOrEmpty(claim.Value))
                        {
                        tmp = Convert.ToInt32(claim.Value);
                        }
                    }

                if (tmp == 1)
                    {
                    //判断
                    if (IsJobUserEnvironment())
                        {
                        return tmp;
                        }
                    }

                return tmp;
                }
            }

        private static readonly ConcurrentDictionary<string, bool> _caches_jobUser = new();
        private bool IsJobUserEnvironment()
            {
            HttpContext? ctx = accessor?.HttpContext;
            if (ctx == null)
                {
                return false;
                }

            string? path = ctx.Request.Path.Value;
            if (_caches_jobUser.ContainsKey(path))
                {
                return _caches_jobUser[path];
                }

            try
                {
                Microsoft.AspNetCore.Http.Features.IFeatureCollection? features = accessor?.HttpContext?.Features;
                if (features == null)
                    {
                    return false;
                    }

                KeyValuePair<Type, object> feature = features.ToList().FirstOrDefault(i => i.Key.FullName == "Microsoft.AspNetCore.Http.Features.IEndpointFeature");

                object? featureObj = feature.Value;
                System.Reflection.PropertyInfo? prop = featureObj?.GetType()?.GetProperty("Endpoint");
                object? endpoint = prop?.GetValue(featureObj);
                prop = endpoint?.GetType().GetProperty("Metadata");
                if (prop == null)
                    {
                    return false;
                    }

                object? metadata = prop.GetValue(endpoint);
                List<object> list = System.Linq.Enumerable.ToList<object>(metadata as IEnumerable<object>);
                object? descriptor = list.FirstOrDefault(i => i.GetType().FullName == "Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor");
                System.Reflection.PropertyInfo? methodinfo = descriptor.GetType().GetProperty("MethodInfo");
                System.Reflection.PropertyInfo? controllerTypeInfo = descriptor.GetType().GetProperty("ControllerTypeInfo");
                System.Reflection.MethodInfo? methodType = methodinfo.GetValue(descriptor) as System.Reflection.MethodInfo;
                List<object> methodAttrs = methodType.GetCustomAttributes(true).ToList();
                Type? controllerType = controllerTypeInfo.GetValue(descriptor) as System.Type;
                List<object> controllerAttrs = controllerType.GetCustomAttributes(true).ToList();

                if (controllerAttrs.Any(i => i.GetType() == typeof(JobUserEnvrionmentAttribute))
                    || methodAttrs.Any(i => i.GetType() == typeof(JobUserEnvrionmentAttribute)))
                    {
                    _caches_jobUser[path] = true;
                    return true;
                    }

                _caches_jobUser[path] = false;
                return false;
                }
            catch (Exception ex)
                {
                Console.WriteLine($"{DateTime.Now.ToCommonStampString()} 判断JobUser环境报错:{ex?.Message}\r\n{ex?.StackTrace}");
                _caches_jobUser[path] = false;
                return false;
                }
            }

        /// <summary>
        /// 用户名
        /// </summary>
        public virtual string UserName
            {
            get
                {
                string tmp = "";
                if (Id == 1)
                    {
                    return "系统用户";
                    }

                StringValues un = new();
                bool? existInHeader = accessor?.HttpContext?.Request.Headers.TryGetValue("un", out un);
                if (existInHeader == true)
                    {
                    string undecode = WebUtility.UrlDecode(un[0]);
                    string[] unarr = undecode.SplitAndTrim(':');
                    if (unarr.IsNotNullOrEmpty() && unarr.Length > 1 && unarr[1].IsNotNullOrEmptyOrWhiteSpace())
                        {
                        return unarr[1].To<string>();
                        }
                    }

                Claim claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "na").FirstOrDefault();
                if (claim != null && !string.IsNullOrEmpty(claim.Value))
                    {
                    tmp = claim.Value.Trim();
                    }

                if (accessor?.HttpContext?.User?.Identity.AuthenticationType == "AuthenticationTypes.Federation")
                    {
                    //集成identityserver
                    claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "name").FirstOrDefault();
                    if (claim != null && !string.IsNullOrEmpty(claim.Value))
                        {
                        tmp = claim.Value;
                        }
                    }

                return tmp;
                }
            }

        /// <summary>
        /// 认证客户端
        /// </summary>
        public virtual string? Client
            {
            get
                {
                Claim claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "sc").FirstOrDefault();
                if (claim != null && !string.IsNullOrEmpty(claim.Value))
                    {
                    return claim.Value.Trim();
                    }

                if (accessor?.HttpContext?.User?.Identity.AuthenticationType == "AuthenticationTypes.Federation")
                    {
                    //集成identityserver
                    claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "client_id").FirstOrDefault();
                    if (claim != null && !string.IsNullOrEmpty(claim.Value))
                        {
                        try
                            {
                            if (claim.Value.EndsWith("WAP"))
                                {
                                return claim.Value[..^3];
                                }
                            }
                        catch
                            {
                            }

                        return claim.Value;
                        }

                    claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "aud").FirstOrDefault();
                    if (claim != null && !string.IsNullOrEmpty(claim.Value))
                        {
                        return claim.Value;
                        }
                    }

                return null;
                }
            }

        /// <summary>
        /// 统一登录标识
        /// </summary>
        public virtual string? UnionId
            {
            get
                {

                Claim claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "un").FirstOrDefault();
                if (claim != null && !string.IsNullOrEmpty(claim.Value))
                    {
                    return claim.Value.Trim();
                    }

                if (accessor?.HttpContext?.User?.Identity.AuthenticationType == "AuthenticationTypes.Federation")
                    {
                    //集成identityserver
                    claim = accessor?.HttpContext?.User?.Claims.Where(a => a.Type == "sid").FirstOrDefault();
                    if (claim != null && !string.IsNullOrEmpty(claim.Value))
                        {
                        return claim.Value;
                        }
                    }

                return null;
                }
            }

        /// <summary>
        /// 认证客户端前缀
        /// </summary>
        public string ClientPrefix => Client.IsNotNullOrEmpty() && Client.Contains(".") ? Client[..Client.IndexOf('.')] : Client;
        }
    }
